﻿using Orchard.FileSystems.Media;
using Orchard.Localization;
using Orchard.Media.Services;
using Orchard.Security;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web.Mvc;

namespace NineSeas.Controllers
{
    public class UploadController: Controller
    {
        private static readonly string avatarPath = "NineSeas\\{USER_ID}";
        private static readonly string temporaryPath = "NineSeas\\Temp\\{USER_ID}";
        private static readonly string booksPath = "NineSeas\\Books\\{BOOK_ID}";
        
        private Localizer T { get; set; }

        private readonly IAuthenticationService _authenticationService;
        private readonly IMediaService _mediaService;
        private readonly IStorageProvider _storageProvider;

        public UploadController(IAuthenticationService authenticationService,
                            IMediaService mediaService,
                            IStorageProvider storageProvider)
        {
            this._authenticationService = authenticationService;
            this._mediaService = mediaService;
            this._storageProvider = storageProvider;
            T = NullLocalizer.Instance;
        }
        [HttpPost]
        public ActionResult BookImage(int? bookId)
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
            {
                return Json(new
                {
                    success = false,
                    message = T("Login Required").Text
                });
            }

            if (Request.Files.Count < 1 || Request.Files[0].ContentLength == 0)
            {
                return Json(new
                {
                    success = false,
                    message = T("You didn't give a file to upload").Text
                });
            }
            
            var file = Request.Files[0];
            Image image = null;
            try
            {
                image = Image.FromStream(file.InputStream, true, true);
            }
            catch //(ArgumentException ex)
            {
                return Json(new
                {
                    success = false,
                    message = T("The file you selected is not a valid image or is corrupted.").Text
                });
            }

            if (image.Width == 0 || image.Height == 0 
                || 6/10 > image.Width/image.Height || image.Width/image.Height > 8/10 
                || image.Width > 256)
            {
                return Json(new
                {
                    success = false,
                    message = T("The dimensions of the image must be approximately 7 x 10 and the width must not larger than 256px.").Text
                });
            }

            var path = bookId.HasValue && bookId.Value >= 0 ?
                booksPath.Replace("{BOOK_ID}", bookId.Value.ToString())
                : temporaryPath.Replace("{USER_ID}", user.Id.ToString());

            EnsurePath(path);

            var filePath = _storageProvider.Combine(path, file.FileName);

            // try to delete the file if exists
            try
            {
                _storageProvider.DeleteFile(filePath);
            }
            catch { }

            return SaveImage(image, filePath);
        }

        [HttpPost]
        public ActionResult Avatar()
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
            {
                return Json(new
                {
                    success = false,
                    message = T("Login Required").Text
                });
            }

            if (Request.Files.Count < 1 || Request.Files[0].ContentLength == 0)
            {
                return Json(new
                {
                    success = false,
                    message = T("You didn't give a file to upload").Text
                });
            }

            var file = Request.Files[0];
            Image image = null;
            try
            {
                image = Image.FromStream(file.InputStream, true, true);
            }
            catch //(ArgumentException ex)
            {
                return Json(new
                {
                    success = false,
                    message = T("The file you selected is not a valid image or is corrupted.").Text
                });
            }

            if (image.Width == 0 || image.Height == 0
                || 9 / 10 > image.Width / image.Height || image.Width / image.Height > 11 / 10
                || image.Width > 256)
            {
                return Json(new
                {
                    success = false,
                    message = T("The dimensions of the image must be approximately 1 x 1 and the width must not larger than 256px.").Text
                });
            }

            var path = avatarPath.Replace("{USER_ID}", user.Id.ToString());
            EnsurePath(path);

            var filePath = _storageProvider.Combine(path, file.FileName);

            // try to delete the file if exists
            try
            {
                _storageProvider.DeleteFile(filePath);
            }
            catch { }

            return SaveImage(image, filePath);
        }

        private void EnsurePath(string path)
        {
            try
            {
                _mediaService.GetMediaFiles(path);
            }
            catch
            {
                _mediaService.CreateFolder("", path);
            }
        }

        private JsonResult SaveImage(Image image, string filePath)
        {
            try
            {
                var stream = new MemoryStream();
                image.Save(stream, image.RawFormat);

                stream.Position = 0;

                _storageProvider.SaveStream(filePath, stream);
                var publicUrl = _storageProvider.GetPublicUrl(filePath);
                return Json(new { success = true, publicUrl = publicUrl, filePath = filePath.Replace(Path.DirectorySeparatorChar, '/') });
            }
            catch (Exception ex)
            {
                return Json(new
                {
                    success = false,
                    message = String.Format("{0}: {1}", T("ERROR: Uploading media file failed:").Text, ex.Message)
                });
            }
        }
    }
}